#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# # author : cypro666
# # date   : 2015.08.01
import sys, json, time
import numpy as np
from threading import Thread
from sklearn import naive_bayes

from magic3.utils import Timer
from magic3.filesystem import *
add_sys_path(grand_dir(__file__))

from skt.base import MethodBase
from skt.utils import _normalize, make_options


class NaiveBayes(MethodBase):
    def __init__(self, parameters={}):
        super().__init__(parameters)

    @property
    def name(self): return 'NaiveBayes'

    def output(self, cls):
        self.Log('output')
        super().output()
        extra = {}

        try:    extra['intercept'] = [float(i) for i in cls.intercept_]
        except: pass

        try:    extra['class_log_prior'] = [float(i) for i in cls.class_log_prior_]
        except: pass

        try:    extra['feature_log_prob'] = [list(v) for v in cls.feature_log_prob_]
        except: pass

        try:    extra['coef'] = [list(v) for v in cls.coef_]
        except: pass

        try:    extra['class_count'] = [float(i) for i in cls.class_count_]
        except: pass

        try:    extra['feature_count'] = [float(i) for i in cls.feature_count_]
        except: pass

        fn = self.json_name()
        json.dump(extra, open(fn, 'w'), indent=4)

    def execute(self):
        self.read_input()

        self._normalize(False, self._param['normalize'])

        if self._param['alpha'] < 1E-6:
            self._param['alpha'] = 1E-6

        CLS = naive_bayes.BernoulliNB

        if self._param['schema'][0] == 'b':
            if self._param['binarize'] < 1.0E-6:
                self._param['binarize'] = 1.0E-6
        else:
            assert self._param['schema'][0] == 'm'
            CLS = naive_bayes.MultinomialNB

        self.save_parameters()

        cprior = None

        if self._param['schema'][0] == 'b':
            biz = self._param['binarize']
            cls = CLS(alpha=self._param['alpha'], fit_prior=True, class_prior=cprior, binarize=biz)

        elif self._param['schema'][0] == 'm':
            cls = CLS(alpha=self._param['alpha'], fit_prior=True, class_prior=cprior)

        cls.fit(self._train, self._label)

        self._results = cls.predict(self._testing)
        self.output(cls)

    def run(self, timeout):
        t = Thread(target=self.execute)
        t.start()
        t.join(timeout)
        if t.is_alive():
            self.Log('timeout!')
        self.Log('exit')


if __name__ == '__main__':
    opts = [('train_file', 'str', []),
            ('label_file', 'str', []),
            ('testing_file', 'str', []),
            ('results_file', 'str', []),
            ('log_file', 'str', []),
            ('schema', 'choice', ['m', 'b']),
            ('normalize', 'choice', ['0', '1', '2']),
            ('alpha', 'float', []),
            ('binarize', 'float', [])]  # using for BernoulliNB only

    parameters = make_options(opts)

    timer = Timer()

    NaiveBayes(parameters).run(1000)

    if __debug__:
        print('elapsed:', timer)




